package com.fstec.ks.master.queue;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import com.sinotn.SinotnLogger;

/**
 * 数据文件引用管理类
 * @Title DataFileRef.java
 * @Package com.sinotn.ks.channel.netty.impl
 * @Description 
 * Copyright: Copyright (c) 2021
 * Company:广东峰上科技有限公司
 * 
 * @author <a href="mailto:xieqj@fstec.com">谢启进</a>
 * @date 2021年4月29日 下午2:31:03
 * @version V1.0
 */
public class DataFileRef {
	private static final boolean trace=SinotnLogger.DEBUG.isDebugEnabled();
	private RandomAccessFile dataRaf;
	private FileChannel dataChannel;
	private File rawFile;
	private int refCount=1;
	
	public DataFileRef(File file, String mode) throws FileNotFoundException{
		this.rawFile=file;
		this.dataRaf=new RandomAccessFile(file, mode);
		this.dataChannel=this.dataRaf.getChannel();
	}
	
	public void incRef(){
		this.refCount++;
		if(trace){
			SinotnLogger.DEBUG.trace("增加虚拟数据文件引用refCount={},path={}", this.refCount, this.rawFile.getAbsolutePath());
		}
	}
	
	public void close(){
		this.refCount--;
		if(this.refCount<1){
			try{
				this.dataChannel.close();
			}catch(Throwable e){
				SinotnLogger.DEBUG.error("关闭文件通道失败"+this.rawFile.getAbsolutePath(), e);
			}
			try{
				this.dataRaf.close();
			}catch(Throwable e){
				SinotnLogger.DEBUG.error("关闭文件流失败"+this.rawFile.getAbsolutePath(), e);
			}
			SinotnLogger.DEBUG.info("物理关闭数据文件path={}", this.rawFile.getAbsolutePath());
		}else if(trace){
			SinotnLogger.DEBUG.trace("虚拟关闭数据文件refCount={},path={}", this.refCount, this.rawFile.getAbsolutePath());
		}
	}

	public void position(long pos) throws IOException {
		this.dataChannel.position(pos);
	}

	public long position() throws IOException {
		return this.dataChannel.position();
	}

	public long size() throws IOException {
		return this.dataChannel.size();
	}

	public int read(ByteBuffer buffer) throws IOException {
		return this.dataChannel.read(buffer);
	}
	
	public File getRawFile(){
		return this.rawFile;
	}

	public long transferTo(long pos, long size, FileChannel target) throws IOException {
		long iRet=this.dataChannel.transferTo(pos, size, target);
		if(iRet!=size){
			SinotnLogger.DEBUG.info("队列数据文件输出文件字节不符[expect={},actual={}]", size, iRet);
		}
		return iRet;
	}
}
